package com.dong.config;

import com.dong.bean.Blue;
import com.dong.bean.Car;
import com.dong.bean.Cat;
import com.dong.bean.MyBeanPostProcessor;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.BeanValidationPostProcessor;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * bean 生命周期  创建--> 初始化--> 销毁
 *   多实例不会管理bean的销毁,需要手动回收
 * 容器管理bean 的生命周期
 * 我们可以自定义初始化和销毁方法,容器在bean 进行到当前生命周期的时候,来调用我们的自定义的初始化和销毁方法
 *    ***   多实例bean,容器不负责进行销毁@Scope  ***
 *      四种方法
 *      1. 指定初始化和销毁方法  [顺序: 4]
 *            指定init-method ,destory-method               最后初始化,最后销毁
 *       2. {@link InitializingBean#afterPropertiesSet()}-->init()   设置好所有的属性  [顺序: 3]
 *          {@link DisposableBean#destroy()}   -->destroy
 *          实验证明,如果使用了接口方法,,如果都定义为同一个方法,那么那个方法只调用一次
 *        3 .jsr 250
 *              {@link   PostConstruct}   {@link  PreDestroy}   这个最先初始化,也最先销毁  [顺序: 2]
 *        4. {@link BeanPostProcessor} ,bean后置处理器,在bean初始化前后进行一些处理工作   这个是对所有的bean初始化的一个加工   [顺序: 1]
 *                  {@link AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization}:
 *  BeanPostProcessor 原理:
 *	populateBean(beanName, mbd, instanceWrapper);//给bean进行属性赋值
 *
 *       {
 * 			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);  执行与初始化方法
 * 		                                  遍历容器中所有的BeanPostProcessor,挨个执行BeforeInitialization,一旦返回null,后面的后置处理器不再执行(跳出for循环)
 * 		    执行自定义初始化方法
 * 			invokeInitMethods(beanName, wrappedBean, mbd);                                                          调用初始化方法
 * 			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);   执行初始化后方法 *
 *       }
 *
 *
 * Spring底层使用的BeanPostProcessor
 *              {@link org.springframework.context.support.ApplicationContextAwareProcessor}
 *              {@link BeanValidationPostProcessor }
 *              {@link InitDestroyAnnotationBeanPostProcessor}   jsr 250 @PostConstruct @PreDestory
 *              {@link AutowiredAnnotationBeanPostProcessor} --> {@link Autowired}
 *
 */
@Configuration
public class T030LifeCycleConfig {
   @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car () {
        return new Car();
    }
   // @Bean(initMethod ="afterPropertiesSet1",destroyMethod = "destroy1")
    @Bean
    public Cat cat() {
       return new Cat();
    }

    /**
     * BeanPostProcess:在任何初始化方法前执行
     * @return
     */
    @Bean
    public BeanPostProcessor beanPostProcessor() {
       return new MyBeanPostProcessor();
    }

    /**
     * 测试没有初始化方法,BeanPostProcessor会不会产生作用:  会的
     * @return
     */
    @Bean
    public Blue blue() {
       return new Blue();
    }
}
